package com.lsm.sm.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import com.sun.image.codec.jpeg.*;
import com.sun.imageio.plugins.bmp.BMPImageReader;
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.jpeg.JPEGImageReader;
import com.sun.imageio.plugins.png.PNGImageReader;

public class ImageUtils {
	public enum WatermarkPosition{
		no,
		topLeft,
		topRight,
		center,
		bottomLeft,
		bottomRight
	}
	/*
	 * get image from file system path.
	 */
	public static Image file2Image( String path ){
		try{
			File file = new File( path );
			return ImageIO.read( file );
		}catch( Exception e ){
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * get image from the class path;
	 */
	public static Image res2Image( String path ){
		BufferedImage image = null;
		try{
			InputStream is = ImageUtils.class.getResourceAsStream( "/" + path );
			image = ImageIO.read( is );
		}catch( IOException e ){
			e.printStackTrace();	
		}
		return image;
	}
	
	public static BufferedImage resizeBySpcifiedWH( BufferedImage src, int width, int height ){
		if( src == null ){
			return null;
		}
		BufferedImage image = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB );
		Graphics2D g = image.createGraphics();
		g.drawImage(src, 0, 0, width, height, null );
		g.dispose();
		return image;
	}

	public static BufferedImage resizeByProportion( BufferedImage src, double factor ){
		if( src == null ){
			return null;
		}

		int width = (int)(src.getWidth()*factor);
		int height = (int)(src.getHeight()*factor);
		BufferedImage image = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB );
		Graphics2D g = image.createGraphics();
		g.drawImage(src.getScaledInstance( width, height, Image.SCALE_SMOOTH ), 0, 0, null );
		g.dispose();

		return image;
	}

	public static BufferedImage resizeByWidth( BufferedImage src, int width ){
		if( src == null ){
			return null;
		}
		double sx = ((double)width)/src.getWidth();
		int height = (int)(sx*src.getHeight());
		BufferedImage image = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB );
		
		Graphics2D g = image.createGraphics();
		g.setRenderingHint(RenderingHints.KEY_RENDERING,
					RenderingHints.VALUE_RENDER_QUALITY);
		g.drawRenderedImage(src,
					AffineTransform.getScaleInstance(sx, sx));
		g.dispose();
		return image;
	}

	public static BufferedImage resizeByHeight( BufferedImage src, int height ){
		if( src == null ){
			return null;
		}
		double sx = ((double)height)/src.getHeight();
		int width = (int)(sx*src.getWidth());
		BufferedImage image = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB );
		
		Graphics2D g = image.createGraphics();
		g.setRenderingHint(RenderingHints.KEY_RENDERING,
					RenderingHints.VALUE_RENDER_QUALITY);
		g.drawImage( image, 0, 0, null);
		g.dispose();
		return image;
	}

	public static BufferedImage resizeByLongSide(  BufferedImage src, int width, int height, Color bgColor ){
		if( src == null ){
			return null;
		}
		int srcWidth = src.getWidth();
		int srcHeight = src.getHeight();
		int tempWidth = width;
	    int tempHeight = height;
		if(srcHeight >= srcWidth)
			tempWidth = (int)Math.round((((double)height*1.0D)/(double)srcHeight)*(double)srcWidth);
		else
			tempHeight = (int)Math.round((((double)width*1.0D)/(double)srcWidth)*(double)srcHeight);
		BufferedImage image = new BufferedImage( tempWidth, tempHeight, 1);
		Graphics2D g = image.createGraphics();
		g.setBackground(bgColor);
		g.clearRect(0, 0, width, height);
		g.drawImage(src.getScaledInstance(tempWidth, tempHeight, 4), width/2-tempWidth/2, height/2-tempHeight/2, null);
		g.dispose();

		return image;
	}

	public static BufferedImage resizeBySmallProportion(  BufferedImage src, int width, int height, Color bgColor ){
		if( src == null ){
			return null;
		}
		int srcWidth = src.getWidth();
		int srcHeight = src.getHeight();
		double sx = (width*1.0D)/srcWidth;
		double sy = (height*1.0D)/srcHeight;
		int tempWidth = width;
		int tempHeight = height;
		if( sx<sy ){
			tempHeight = (int)(sx*srcHeight);
		}else{
			tempWidth = (int)(sy*srcWidth);
		}

		BufferedImage image = new BufferedImage( tempWidth, tempHeight, 1);
		Graphics2D g = image.createGraphics();
		g.setBackground(bgColor);
		g.clearRect(0, 0, width, height);
		g.drawImage(src.getScaledInstance(tempWidth, tempHeight, 4), width/2-tempWidth/2, height/2-tempHeight/2, null);
		g.dispose();

		return image;
	}
	
	public static OutputStream encode( BufferedImage src, int quality ){
		ByteArrayOutputStream imageos = new ByteArrayOutputStream();
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder( imageos );
		
		//System.out.println( "hehe" + encoder );
		//会此起 空指针异常;
		/*JPEGEncodeParam params = encoder.getJPEGEncodeParam();
		quality = Math.max( 0, Math.min( quality, 100 ) );
		params.setQuality( (float)quality/100.0f, false );
		encoder.setJPEGEncodeParam( params );*/
		
		try{
			encoder.encode( src );
		}catch( IOException e ){
			e.printStackTrace();
		}
		return imageos;
	}
	
	public static void encode( BufferedImage src, OutputStream out, int quality ){
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder( out );
		JPEGEncodeParam params = encoder.getJPEGEncodeParam();
		quality = Math.max( 0, Math.min( quality, 100 ) );
		params.setQuality( (float)quality/100.0f, false );
		encoder.setJPEGEncodeParam( params );
		try{
			encoder.encode( src );
			out.close();
		}catch( IOException e ){
			e.printStackTrace();
		}
	}
	
	public static InputStream imageInstream( BufferedImage src ){
		ByteArrayOutputStream os = (ByteArrayOutputStream)encode( src, 88 );
		ByteArrayInputStream imageis = new ByteArrayInputStream(os.toByteArray());
		return imageis;
	}
	
	
	public static BufferedImage rotate( BufferedImage src, double degree, Color bgColor ){
		int width = src.getWidth();
		int height = src.getHeight();
		int w=0, h=0, x=0, y=0;
		
		degree = degree%360;
		if( degree < 0 ){
			degree = 360 + degree;
		}
		double angle = Math.toRadians( degree );
		
		/** 
         *确定旋转后的图象的高度和宽度
         */
        if(degree == 180 || degree == 0 || degree == 360){
            w = width;
            h = height;
        } else if(degree == 90 || degree == 270){
            w = height;
            h = width;
        }else{
            int d = width + height;
            w = (int) (d * Math.abs(Math.cos(angle)));
            h = (int) (d * Math.abs(Math.sin(angle)));
        }
        
        x = (w/2)-(width/2);//确定原点坐标
        y = (h/2)-(height/2);
		
		BufferedImage image = new BufferedImage( w, h, src.getType() );
		Graphics2D g = image.createGraphics();
		if( bgColor == null ){
			image  = g.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);  
		}else{
			g.setColor( bgColor );
			g.fillRect( 0, 0, w, h );
		}
		AffineTransform at = new AffineTransform();
        at.rotate(angle, w/2, h/2);//旋转图象
        at.translate(x, y);
        AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);  
        op.filter(src, image);
		return image;
	}
	
	//添加水印
	public static BufferedImage addWaterMark( BufferedImage src, BufferedImage watermark, WatermarkPosition position, int alpha, Color bgColor ){
		if( src==null || watermark==null ){
			return null;
		}
		
		int srcWidth = src.getWidth();
        int srcHeight = src.getHeight();
        BufferedImage image = new BufferedImage(srcWidth, srcHeight, 1);
        Graphics2D g = image.createGraphics();
        
        g.setBackground(bgColor);
        g.clearRect(0, 0, srcWidth, srcHeight);
        g.drawImage(src, 0, 0, null);
        g.setComposite(AlphaComposite.getInstance(10, (float)alpha/100F));
       
        int watermarkWidth = watermark.getWidth();
        int watermarkHeight = watermark.getHeight();
        int x = srcWidth - watermarkWidth;
        int y = srcHeight - watermarkHeight;
		if (position == WatermarkPosition.topLeft) {
			x = 0;
			y = 0;
		} else if (position == WatermarkPosition.topRight) {
			x = srcWidth - watermarkWidth;
			y = 0;
		} else if (position == WatermarkPosition.center) {
			x = (srcWidth - watermarkWidth) / 2;
			y = (srcHeight - watermarkHeight) / 2;
		} else if (position == WatermarkPosition.bottomLeft) {
			x = 0;
			y = srcHeight - watermarkHeight;
		} else if (position == WatermarkPosition.bottomRight) {
			x = srcWidth - watermarkWidth;
			y = srcHeight - watermarkHeight;
		}

        g.drawImage(watermark, x, y, watermarkWidth, watermarkHeight, null);
        g.dispose();
        return image;
	}
	
	public static String getFormatName( ImageInputStream input ){
		String formatName = null;
		Iterator<ImageReader> it = ImageIO.getImageReaders(input);

		if (!it.hasNext()) {
			return null;
		}

		ImageReader imageReader = (ImageReader) it.next();
		if (imageReader instanceof JPEGImageReader)
			formatName = "jpg";
		else if (imageReader instanceof GIFImageReader)
			formatName = "gif";
		else if (imageReader instanceof BMPImageReader)
			formatName = "bmp";
		else if (imageReader instanceof PNGImageReader)
			formatName = "png";
		return formatName;
	}
}